package com.multitrack.map;

import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Locale;

import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.location.Location;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;

import com.facebook.android.CustomFacebook;
import com.google.android.maps.GeoPoint;
import com.multitrack.datatype.CurrLocation;
import com.multitrack.datatype.CurrLocationList;
import com.multitrack.datatype.Event;
import com.multitrack.datatype.EventData;
import com.multitrack.datatype.GPS;
import com.multitrack.datatype.Identity;
import com.multitrack.datatype.IdentityList;
import com.multitrack.datatype.MemberGPS;
import com.multitrack.datatype.MemberGPSList;
import com.multitrack.datatype.MyLocation;
import com.multitrack.datatype.STATE;
import com.multitrack.datatype.SocketMessage;
import com.multitrack.datatype.TYPE;
import com.multitrack.datatype.TrackSelectArg;
import com.multitrack.main.R;
import com.multitrack.main.data.MembersCompare;
import com.multitrack.map.datatype.GeoPoints;
import com.multitrack.map.datatype.Marker;
import com.multitrack.map.datatype.Polyline;
import com.multitrack.map.mixare.MixView;
import com.multitrack.map.util.Convert;
import com.multitrack.util.CloseAlertDialog;
import com.multitrack.util.CommunicationManager;
import com.multitrack.util.EventSQLite;
import com.multitrack.util.MemberListAdapter;
import com.multitrack.util.ThreadManager;

public class EventMapActivity extends BasicMapActivity {

	private final String TAG = "EventMapActivity";

	// NFC
	private NfcAdapter mAdapter;
	private NdefMessage mMessage;

	private Event currEvent;
	private MyLocation myLoc;

	// SQLite
	private EventSQLite mHelper;

	private MemberListAdapter adapter;
	private ListView memberListView;

	private EventData eventData;
	private Identity member;
	private IdentityList members;
	private MemberGPSList memGPSList;

	private CurrLocationList currLocList;
	GeoPoints geoPoints;
	private String myId;

	private CommunicationManager quitEvent;
	private CommunicationManager requestMemberList;
	private CommunicationManager recordLocation;
	private CommunicationManager requestMemberTrack;
	private CommunicationManager requestAllMemberCurrLoc;
	private CommunicationManager requestTrackAndMove;
	private CommunicationManager sendDestination;
	private CommunicationManager requestChangeLeader;
	private CommunicationManager requestBanMember;

	private LinearLayout mLayout;
	private LinearLayout otherTrackLayout;

	// ImageUpdate
	private ImageView imgUpdate;

	// 트랙
	protected TrackSelectArg trackSelectArg;

	// 다른 사람 트랙
	private Polyline otherLines;

	//
	private Marker allMemberMarker;
	private Marker memberMarker;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		mLayout = (LinearLayout) findViewById(R.id.memberListLayout);
		otherTrackLayout = (LinearLayout) findViewById(R.id.otherTrackLayout);
		memberListView = (ListView) findViewById(R.id.memberListView);
		members = new IdentityList();
		adapter = new MemberListAdapter(this, R.layout.member_item_activity,
				members);
		memberListView.setAdapter(adapter);
		memberListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

		registerForContextMenu(memberListView);

		mAdapter = NfcAdapter.getDefaultAdapter(this);
		if (mAdapter == null) {
			// NFC 비 활성화 - 태그 쓰기 불가능
		}

		mHelper = new EventSQLite(this);
		myId = mHelper.dbGetMyId();

		Intent getIntent = getIntent();
		currEvent = (Event) getIntent.getSerializableExtra(TYPE.EVENT);
		if (mHelper.dbIsEvent(currEvent.getId())) {
			mHelper.dbUpdateEvent(currEvent);
		} else {
			mHelper.dbInsertEvent(currEvent);
			mHelper.dbInsertEntrant(currEvent.getId(), mHelper.dbGetMyId());
		}
		
		member = new Identity();
		geoPoints = new GeoPoints();

		// NFC TAG 메시지 생성 및 등록
		mMessage = createEventNdefMsg(currEvent);

		// Image Update
		imgUpdate = (ImageView) findViewById(R.id.imgUpdate);
		imgUpdate.setVisibility(View.VISIBLE);

		allMemberMarker = new Marker(mCustomMap, getApplicationContext(),
				R.drawable.member);
		memberMarker = new Marker(mCustomMap, getApplicationContext(),
				R.drawable.member);
		
		/* 모든 사람들에 마지막 위치를 서버에서 다운 후 SQLite에 저장하고
		 * 참가자에 마지막 위치에 마커를 그린다.
		 */
		excuteRequestAllMembersCurrLoc();
	}

	/*
	 * NFC 관련 함수 부분 시작~ 메소드: createEventNdefMsg 작성일: 2012-09-14 작성자: 백봉준 수정일:
	 * 코멘트: NdefMessage > NdefRecord [] > NdefRecord > Text Data
	 */
	private NdefMessage createEventNdefMsg(Event event) {

		NdefRecord[] records = new NdefRecord[2];

		records[0] = createTextRecord(event.getId(), Locale.KOREAN, true);
		records[1] = createTextRecord(event.getName(), Locale.KOREAN, true);

		NdefMessage mMessage = new NdefMessage(records);

		return mMessage;
	}

	private NdefRecord createTextRecord(String text, Locale locale,
			boolean encodeInUtf8) {
		byte[] langBytes = locale.getLanguage().getBytes(
				Charset.forName("US-ASCII"));
		myId = mHelper.dbGetMyId();

		Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset
				.forName("UTF-16");
		byte[] textBytes = text.getBytes(utfEncoding);

		int utfBit = encodeInUtf8 ? 0 : (1 << 7);
		char status = (char) (utfBit + langBytes.length);

		byte[] data = new byte[1 + langBytes.length + textBytes.length];
		data[0] = (byte) status;
		System.arraycopy(langBytes, 0, data, 1, langBytes.length);
		System.arraycopy(textBytes, 0, data, 1 + langBytes.length,
				textBytes.length);

		return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT,
				new byte[0], data);
	}

	/*
	 * NFC 관련 함수 부분 끝!
	 */

	@Override
	public void onLocationChanged(Location location) {

		switch (getCtrlState()) {
		case PLAY:
			// 저장 및 선 그리기 시작
			mHelper.dbAddMyTrack(currEvent.getId(), location);
			drawLine(location);

			myLoc = new MyLocation(currEvent.getId(), mHelper.dbGetMyId(),
					new GPS(location));
			excuteRecordLocation(myLoc);
			break;

		case PAUSE:
			// 저장 및 선 그리기 중지
			break;

		case STOP:
			// 저장 및 선그리기 중지
			// 저장 여부
			// 예 -> 저장 후 맵 클리어
			// 아니오 -> 취소
			break;
		}
	}

	// Update Button 클릭 시
	@Override
	public void mOnClick(View v) {
		super.mOnClick(v);

		switch (v.getId()) {

		case R.id.imgUpdate:

			if (mLayout.isShown()) {

				excuteRequestMemberList();

			} else {

				excuteRequestAllMembersCurrLoc();
			}

			break;
		}
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		super.onPrepareOptionsMenu(menu);
		getMenuInflater().inflate(R.menu.option, menu);
		return true;
	}

	// 옵션 메뉴 선택 시
	public boolean onOptionsItemSelected(MenuItem item) {

		Log.i(TAG, String.valueOf(item.getItemId()));
		CustomFacebook cf = new CustomFacebook(this);
		switch (item.getItemId()) {

		// 참가자
		case R.id.memberList:
			if (!mLayout.isShown()) {
				mLayout.setVisibility(View.VISIBLE);
				imgPlay.setVisibility(View.INVISIBLE);
				imgPause.setVisibility(View.INVISIBLE);
				imgStop.setVisibility(View.INVISIBLE);
				excuteRequestMemberList();
			}
			break;

		case R.id.destination:
			if (!dLayout.isShown()) {
				dLayout.setVisibility(View.VISIBLE);
				imgUpdate.setVisibility(View.INVISIBLE);
				imgPlay.setVisibility(View.INVISIBLE);
				imgPause.setVisibility(View.INVISIBLE);
				imgStop.setVisibility(View.INVISIBLE);
			}
			break;

		case R.id.mixare:
			excuteRequestAllMembersCurrLoc();
			Intent intent = new Intent(EventMapActivity.this, MixView.class);
			startActivity(intent);

			break;

		case R.id.logout:
			cf.logout();
			break;
		case R.id.login:
			cf.login();
			break;

		case R.id.capture:
			cf.screenCapture(mCustomMap);
			break;
		}
		return false;
	}

	// 컨텍스트 메뉴
	@Override
	public void onCreateContextMenu(ContextMenu menu, View view,
			ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, view, menuInfo);

		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.member_context_menu, menu);

		if (currEvent.getLeaderId().equals(myId)) {
			MenuItem item = (MenuItem) menu.findItem(R.id.changedLeader);
			item.setVisible(true);
			item = (MenuItem) menu.findItem(R.id.ban);
			item.setVisible(true);
		}
	}

	// 컨텍스트 메뉴 선택 시
	@Override
	public boolean onContextItemSelected(MenuItem item) {

		AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item
				.getMenuInfo();

		int selectPosition = menuInfo.position;

		String event_id = currEvent.getId();
		String member_id = members.get(selectPosition).getId();
		long time = mHelper.dbGetLastTime(event_id, member_id);

		trackSelectArg = new TrackSelectArg();
		trackSelectArg.setEvent_id(event_id);
		trackSelectArg.setMember_id(member_id);
		trackSelectArg.setTime(time);

		// TODO:

		switch (item.getItemId()) {

		case R.id.searchTrack:
			executeGetTrack(trackSelectArg);
			break;

		case R.id.moveLocation:
			executeGetTrackAndMove(trackSelectArg);
			break;

		case R.id.changedLeader:
			currEvent.setLeaderId(member.getId());
			executeRequestChangeLeader();
			break;

		case R.id.ban:
			executeRequestBanMember();
			break;
		}

		return false;
	}

	@Override
	public void onResume() {
		super.onResume();
		if (mAdapter != null) {
			mAdapter.enableForegroundNdefPush(this, mMessage);
		}
	}

	@Override
	public void onPause() {
		super.onPause();
		if (mAdapter != null) {
			mAdapter.disableForegroundNdefPush(this);
		}
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		mHelper.close();
	}

	@Override
	public boolean onKeyUp(int KeyCode, KeyEvent event) {

		if (mLayout.isShown()) {
			mLayout.setVisibility(View.INVISIBLE);
			updateControllerImg(getCtrlState());
			return true;

		} else if (dLayout.isShown() && KeyCode == KeyEvent.KEYCODE_BACK) {
			dLayout.setVisibility(View.INVISIBLE);
			imgUpdate.setVisibility(View.VISIBLE);
			updateControllerImg(getCtrlState());
			return true;
		}

		return super.onKeyUp(KeyCode, event);

	}

	@Override
	protected void onKeyUpBack() {
		if (otherTrackLayout.isShown()) {
			otherTrackLayout.setVisibility(View.INVISIBLE);

			mCustomMap.getOverlays().remove(otherLines);
			beginMarker.clear();
			memberMarker.clear();
			
			drawMarkerLastLoc();
			
			// TODO
			GeoPoint point = mHelper.dbGetLastPoint(currEvent.getId(),
					mHelper.dbGetMyId());
			if (point != null) {
				mapControl.animateTo(point);

				if (lines != null && lines.size() > 0) {
					mCustomMap.getOverlays().add(lines);
					beginMarker.draw(lines.get(0));
				}

			}
			return;
		}

		OnClickListener listener = new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				excuteQuit();
			}
		};
		new CloseAlertDialog(this, R.string.notice,
				"정말 나가시겠습니까?\n(R.string 등록)", listener, null).show();
	}

	public void onShowDialog() {
		if (!currEvent.getLeaderId().equals(myId)) {
			return;
		}

		OnClickListener listener = new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				targetPoint = searchPoint;
				flagMarker.draw(targetPoint);
				excuteSendDestination(Convert.toGPS(targetPoint));
			}
		};
		new CloseAlertDialog(EventMapActivity.this, R.string.destination_title,
				R.string.destination_message, listener, null).show();
	}

	private Handler mHandler = new Handler() {

		SocketMessage message;
		STATE resultState;
		Object resultValue;

		@Override
		public void handleMessage(Message msg) {

			message = SocketMessage.getEnum(msg.arg1);
			resultState = STATE.getEnum(msg.what);
			resultValue = msg.obj;

			switch (message) {

			case EVENT_QUIT:
				eventQuit();
				break;

			case CURR_LOCATION:
				receiveCurrLocation();
				break;

			case REQUEST_MEMBER_LIST:
				receiveMemberList();
				break;

			case RECORD_LOCATION:
				recordLocation();
				break;

			case REQUEST_MEMBER_TRACK:
			case REQUEST_MEMBER_TRACK_MOVE:
				receiveTrack();
				break;

			case REQUEST_ALL_MEMBER_CURRENT_LOCATION:
				receiveCurrLocationAll();
				break;

			case SEND_DESTINATION:
				sendDestination();
				break;

			case CHANGE_LEADER:
				receiveChangeLeader();
				break;

			case BAN_MEMBER:
				receiveBanMember();
				break;

			default:
				unknownMessage(message);
				break;
			}
		}

		// ////////////////////////////////////////////////////////////////////
		// 이벤트를 나갑니다.
		// ////////////////////////////////////////////////////////////////////
		private void eventQuit() {

			switch (resultState) {
			case SOCKET_SUCCESS:
				eventQuitSuccess();
				break;

			case SOCKET_FAIL:
				uponFail();
				break;

			case SOCKET_EXCEPTION:
				OnClickListener listener = new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						excuteQuit();
					}
				};
				UponException(listener, null);
				break;

			default:
				unknownMessage(resultState);
				break;
			}
		}

		private void eventQuitSuccess() {
			OnClickListener listener = new OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					mHelper.dbDeleteEvent(currEvent.getId());
					finish();
				}
			};

			switch ((SocketMessage) resultValue) {
			case SQL_QUERY_SUCCESS:
				mHelper.dbDeleteEvent(currEvent.getId());
				finish();
				break;

			case SQL_QUERY_FAIL:
				new CloseAlertDialog(EventMapActivity.this, R.string.notice,
						"이벤트 나가기 실패", listener);
				break;

			case SQL_QUERY_ERROR:
				new CloseAlertDialog(EventMapActivity.this, R.string.notice,
						"방 정보를 찾을 수 없습니다.(R.string)", listener);
				break;

			default:
				unknownMessage((SocketMessage) resultValue);
				break;
			}

		}

		// event member

		private void receiveMemberList() {

			switch (resultState) {
			case SOCKET_SUCCESS:
				if (members != null) {
					members.clear();
				}

				Iterator<Identity> it = ((IdentityList) resultValue).iterator();
				while (it.hasNext()) {
					// TODO
					Identity member = it.next();
					mHelper.dbInsertMember(member);
					members.add(member);
				}
				adapter.notifyDataSetChanged();
				
				// 멤버 비교 및 체크
				boolean isNewMember = true;
				MembersCompare membersCompare;
				membersCompare = mHelper.dbGetEntrantList(currEvent.getId());
				for(int i = 0; i < members.size(); i++) {
					up :
					for(int j = 0; j < membersCompare.size(); j++) {
						
						if(membersCompare.get(j).isFound()){
							continue;
						}
						else if( members.get(i).getId().equals(membersCompare.get(j).getMemberId()) ) {
								membersCompare.get(j).setFound(true);
								isNewMember = false;
								break up;
						}
						else {
							membersCompare.get(j).setFound(false);
							continue;
						}
						
					}
					
					// 내부 DB에 새로운 참가자 추가
					if(isNewMember == true) {
						mHelper.dbInsertMember(members.get(i).getId(), members.get(i).getName());
						mHelper.dbInsertEntrant(currEvent.getId(), members.get(i).getId());
					}

					isNewMember = true;

				}
				
				// 서버에 없는 SQLite에 멤버 삭제
				for(int i = 0; i < membersCompare.size(); i++) {
					if( !membersCompare.get(i).isFound() ) {
						mHelper.dbDeleteEntrant(currEvent.getId(), membersCompare.get(i).getMemberId());
						mHelper.dbDeleteMember(membersCompare.get(i).getMemberId());
					}
				}
				// 내부 DB에서 참가자 마지막 위치 마커 그리기
				drawMarkerLastLoc();
				break;

			case SOCKET_FAIL:
				uponFail();
				break;

			case SOCKET_EXCEPTION:
				OnClickListener listener = new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						excuteRequestMemberList();
					}
				};
				UponException(listener);
				break;

			default:
				unknownMessage(resultState);
				break;
			}

		}

		// record Location

		private void recordLocation() {

			switch (resultState) {
			case SOCKET_SUCCESS:
				recordLocationSuccess();
				break;

			case SOCKET_FAIL:
				uponFail();
				break;

			case SOCKET_EXCEPTION:
				OnClickListener listener = new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						excuteRecordLocation(myLoc);
					}
				};
				UponException(listener);
				break;

			default:
				unknownMessage(resultState);
				break;
			}

		}

		private void recordLocationSuccess() {

			switch ((SocketMessage) resultValue) {

			case SQL_QUERY_SUCCESS:
				Log.i(TAG, SocketMessage.SQL_QUERY_SUCCESS.toString());
				break;

			default:
				unknownMessage((SocketMessage) resultValue);
				break;

			}

		}

		// Track 요청

		private void receiveTrack() {

			switch (resultState) {
			case SOCKET_SUCCESS:
				receiveTrackSuccess();
				break;

			case SOCKET_FAIL:
				uponFail();
				break;

			case SOCKET_EXCEPTION:
				OnClickListener listener = new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						executeGetTrack(trackSelectArg);
					}
				};
				UponException(listener);
				break;

			default:
				unknownMessage(resultState);
				break;
			}

		}

		// TODO
		private void receiveTrackSuccess() {
			MemberGPS memberGPS = (MemberGPS) resultValue;
			mHelper.dbAddTracks(currEvent.getId(), memberGPS);

			switch (message) {
			case REQUEST_MEMBER_TRACK:
				if (!otherTrackLayout.isShown()) {
					otherTrackLayout.setVisibility(View.VISIBLE);
				}

				GeoPoints points = mHelper.dbGetTrackPoints(currEvent.getId(),
						memberGPS.getId());

				if (points == null || points.size() == 0)
					break;

				allMemberMarker.clear();
				
				if (otherLines == null) {
					otherLines = new Polyline(points);
				} else {
					mCustomMap.getOverlays().remove(otherLines);
					otherLines.setGeoPoints(points);
				}
				mCustomMap.getOverlays().add(otherLines);

				if (points.size() > 0) {
					beginMarker.clear();
					beginMarker.draw(points.get(points.size() - 1));
				}
				if (points.size() > 1) {
					memberMarker.clear();
					memberMarker.draw(points.get(0));
				}

				if (lines != null) {
					mCustomMap.getOverlays().remove(lines);
				}

				mCustomMap.invalidate();
				break;

			case REQUEST_MEMBER_TRACK_MOVE:
				break;
			}
			GeoPoint point;
			point = mHelper
					.dbGetLastPoint(currEvent.getId(), memberGPS.getId());
			if (point == null) {
				new CloseAlertDialog(EventMapActivity.this, R.string.notice,
						"위치정보가 없습니다.(R.string)", null).show();
			} else {
				if (mLayout.isShown()) {
					mLayout.setVisibility(View.INVISIBLE);
				}
				mapControl.animateTo(point);
			}

			updateControllerImg(getCtrlState());

		}

		// onCreate 시 모든 멤버 데이터 가져오기
		public void receiveCurrLocationAll() {

			switch (resultState) {
			case SOCKET_SUCCESS:
				receiveCurrLocationAllSuccess();
				break;

			case SOCKET_FAIL:
				uponFail();
				break;

			case SOCKET_EXCEPTION:
				OnClickListener listener = new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						excuteRequestAllMembersCurrLoc();
					}
				};
				UponException(listener);
				break;

			default:
				unknownMessage(resultState);
				break;
			}
		}

		private void receiveCurrLocationAllSuccess() {

			currLocList = new CurrLocationList();
			currLocList = (CurrLocationList) resultValue;

			for (int i = 0; i < currLocList.size(); i++) {
				CurrLocation tCurrLoc = currLocList.get(i);

				if (tCurrLoc.getId().equals(mHelper.dbGetMyId()))
					continue;

				mHelper.dbInsertTrack(currEvent.getId(), currLocList.get(i));
			}

			drawMarkerLastLoc();

		}

		public void receiveCurrLocation() {

			switch (resultState) {
			case SOCKET_SUCCESS:
				receiveCurrLocationSuccess();
				break;

			case SOCKET_FAIL:
				uponFail();
				break;

			case SOCKET_EXCEPTION:
				OnClickListener listener = new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						executeGetTrackAndMove(trackSelectArg);
					}
				};
				UponException(listener);
				break;

			default:
				unknownMessage(resultState);
				break;
			}
		}

		private void receiveCurrLocationSuccess() {

			// 코드작성

		}

		private void sendDestination() {

			switch (resultState) {

			case SOCKET_SUCCESS:
				// TODO
				mHelper.dbUpdateEventTarget(currEvent.getId(), targetPoint);
				break;

			case SOCKET_FAIL:
				uponFail();
				break;

			case SOCKET_EXCEPTION:
				OnClickListener listener = new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						excuteSendDestination(Convert.toGPS(targetPoint));
					}
				};
				UponException(listener);
				break;

			default:
				break;
			}
		}

		private void receiveChangeLeader() {

			switch (resultState) {

			case SOCKET_SUCCESS:
				// TODO: TEST
				mHelper.dbUpdateLeader((String) resultValue);
				break;

			case SOCKET_FAIL:
				uponFail();
				break;

			case SOCKET_EXCEPTION:
				OnClickListener listener = new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						executeRequestChangeLeader();
					}
				};
				UponException(listener);
				break;

			default:
				break;
			}
		}

		private void receiveBanMember() {

			switch (resultState) {

			case SOCKET_SUCCESS:
				// TODO: test
				mHelper.dbDeleteMember((String) resultValue);
				break;

			case SOCKET_FAIL:
				uponFail();
				break;

			case SOCKET_EXCEPTION:
				OnClickListener listener = new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						executeRequestBanMember();
					}
				};
				UponException(listener);
				break;

			default:
				break;
			}
		}

		// ////////////////////////////////////////////////////////////////////
		// 공용 메소드
		// ////////////////////////////////////////////////////////////////////
		private void uponFail() {
			OnClickListener listener = new OnClickListener() {

				public void onClick(DialogInterface dialog, int which) {
					finish();
				}
			};

			new CloseAlertDialog(EventMapActivity.this, R.string.notice,
					"죄송합니다.\n서버 접속이 끊겼습니다.(R.string)", listener).show();
		}

		private void UponException(OnClickListener listener) {
			new CloseAlertDialog(EventMapActivity.this, R.string.notice,
					"서버 연결에 실패했습니다.(R.string)", listener).show();
		}

		private void UponException(OnClickListener pListener,
				OnClickListener nListener) {
			new CloseAlertDialog(EventMapActivity.this, R.string.notice,
					"서버 연결에 실패했습니다.\n다시 연결하시겠습니까?(R.string)", pListener,
					nListener).show();
		}

		private void unknownMessage(STATE state) {
			new CloseAlertDialog(EventMapActivity.this, R.string.notice,
					"알 수 없는 STATE (R.string) - " + state.name(), null).show();

		}

		private void unknownMessage(SocketMessage message) {
			new CloseAlertDialog(EventMapActivity.this, R.string.notice,
					"알 수 없는 MESSAGE (R.string) - " + message.name(), null)
					.show();
		}

	};

	private void excuteQuit() {

		if (ThreadManager.isInThread(quitEvent) == false) {

			quitEvent = new CommunicationManager();
			ThreadManager.excute(quitEvent, mHandler, SocketMessage.EVENT_QUIT,
					new EventData(mHelper.dbGetEventID(), mHelper.dbGetMyId()));
			try {
				quitEvent.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	private void excuteRequestMemberList() {

		if (ThreadManager.isInThread(requestMemberList) == false) {

			requestMemberList = new CommunicationManager();
			ThreadManager.excute(requestMemberList, mHandler,
					SocketMessage.REQUEST_MEMBER_LIST, currEvent.getId());
		}
	}

	private void excuteRecordLocation(MyLocation myLoc) {

		if (ThreadManager.isInThread(recordLocation) == false) {

			recordLocation = new CommunicationManager();
			ThreadManager.excute(recordLocation, mHandler,
					SocketMessage.RECORD_LOCATION, myLoc);
			try {
				recordLocation.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

	}

	private void executeGetTrack(TrackSelectArg trackSelectArg) {
		if (ThreadManager.isInThread(requestMemberTrack) == false) {

			requestMemberTrack = new CommunicationManager();
			ThreadManager.excute(requestMemberTrack, mHandler,
					SocketMessage.REQUEST_MEMBER_TRACK, trackSelectArg);
		}
	}

	private void executeGetTrackAndMove(TrackSelectArg trackSelectArg) {

		// TODO
		if (ThreadManager.isInThread(requestMemberTrack) == false) {

			requestMemberTrack = new CommunicationManager();
			ThreadManager.excute(requestMemberTrack, mHandler,
					SocketMessage.REQUEST_MEMBER_TRACK_MOVE, trackSelectArg);
		}
	}

	private void excuteRequestAllMembersCurrLoc() {

		if (ThreadManager.isInThread(requestAllMemberCurrLoc) == false) {

			requestAllMemberCurrLoc = new CommunicationManager();
			ThreadManager.excute(requestAllMemberCurrLoc, mHandler,
					SocketMessage.REQUEST_ALL_MEMBER_CURRENT_LOCATION,
					currEvent.getId());

			try {
				requestAllMemberCurrLoc.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

	}

	private void excuteSendDestination(GPS destination) {

		if (ThreadManager.isInThread(sendDestination) == false) {

			sendDestination = new CommunicationManager();
			ThreadManager.excute(sendDestination, mHandler,
					SocketMessage.SEND_DESTINATION, destination);
		}
	}

	private void executeRequestChangeLeader() {

		if (ThreadManager.isInThread(requestChangeLeader) == false) {

			requestChangeLeader = new CommunicationManager();
			ThreadManager.excute(requestChangeLeader, mHandler,
					SocketMessage.CHANGE_LEADER, currEvent);

			try {
				requestChangeLeader.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	private void executeRequestBanMember() {

		if (ThreadManager.isInThread(requestBanMember) == false) {

			requestBanMember = new CommunicationManager();
			ThreadManager.excute(requestBanMember, mHandler,
					SocketMessage.BAN_MEMBER, eventData);

			try {
				requestBanMember.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	private void drawMarkerLastLoc() {
		allMemberMarker.clear();
		CurrLocationList locList = mHelper.dbGetLastLocation();
		for (int i = 0; i < locList.size(); i++) {
			CurrLocation loc = locList.get(i);
			allMemberMarker.addDraw(Convert.toGeoPoint(loc.getGps()),
					loc.getId(), loc.getName());
		}
	}
}
